Skip to content

fix: maintain topmost modal non-inert#3206

Merged
MartinCupela merged 1 commit into
masterfrom
fix/remove-inert-from-topmost-modal
Jun 4, 2026
Merged

fix: maintain topmost modal non-inert#3206
MartinCupela merged 1 commit into
masterfrom
fix/remove-inert-from-topmost-modal

Conversation

@MartinCupela

@MartinCupela MartinCupela commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

🎯 Goal

When topmost modal was removed the inert property was not updated on the new topmost modal. This PR fixes it.

Summary by CodeRabbit

  • Bug Fixes

    • Improved dialog state tracking for more accurate open/closed status in DialogManager
    • Fixed modal focus management and keyboard navigation in stacked modals
    • Enhanced modal closing behavior to properly synchronize with open prop changes
    • Corrected tab index accessibility for topmost and underlying modals
  • Tests

    • Added comprehensive coverage for modal stacking scenarios and focus restoration
    • Enhanced test coverage for dialog state transitions and removal handling

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. πŸŽ‰

ℹ️ Recent review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f9b1c9a6-555a-4b9a-be95-e4406ce38bbb

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 4c934ae and 98bd5df.

πŸ“’ Files selected for processing (4)
  • src/components/Dialog/__tests__/DialogsManager.test.ts
  • src/components/Dialog/service/DialogManager.ts
  • src/components/Modal/GlobalModal.tsx
  • src/components/Modal/__tests__/GlobalModal.test.tsx

πŸ“ Walkthrough

Walkthrough

DialogManager's openedDialogIds stack now accurately tracks dialog open/closed state during settings updates, removal marking, and removal cancellation. GlobalModal syncs its open prop directly to dialog state and manages focus via conditional tabIndex. Tests verify stack transitions and focus restoration in stacked modal scenarios.

Changes

Dialog Focus and Stack Management

Layer / File(s) Summary
DialogManager openedDialogIds state transitions
src/components/Dialog/service/DialogManager.ts
getOrCreate conditionally rebuilds openedDialogIds based on isOpen state during settings updates; markForRemoval immediately removes the dialog id; cancelPendingRemoval conditionally restores it based on isOpen.
DialogManager removal and cancellation tests
src/components/Dialog/__tests__/DialogsManager.test.ts
New tests verify that markForRemoval removes the dialog from openedDialogIds immediately, and that cancelPendingRemoval (via getOrCreate) restores it when the dialog is isOpen.
GlobalModal open prop sync and focus management
src/components/Modal/GlobalModal.tsx
useEffect now closes the dialog when open becomes false and returns early; dialog surface tabIndex is set to 0 when topmost, βˆ’1 otherwise, to manage focus and interactivity of stacked modals.
GlobalModal stacked modal and focus restoration tests
src/components/Modal/__tests__/GlobalModal.test.tsx
New test fixtures (RemovableChildModalFixture, CloseChildModalFixture) and test cases verify tabIndex behavior in stacked scenarios and that underlying modals restore inert, aria-modal, and tabindex when the topmost modal closes via Escape or open prop changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • GetStream/stream-chat-react#3203: Both PRs modify DialogManager's openedDialogIds stack handling and topmost modal behavior for dialog removal and cancellation.

Suggested reviewers

  • arnautov-anton
  • oliverlaz

Poem

🐰 Modals stacking high, now they know their place,
Focus flows smoothly through dialog space,
When the topmost fades away with grace,
The layer below shines brightβ€”no lost trace! ✨

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description includes the Goal section explaining the issue (inert property not updated on new topmost modal), but lacks Implementation details and UI Changes sections from the template. Add Implementation details section explaining how the fix works (state transitions, effect changes, tabindex updates) and clarify if UI Changes section is needed for this fix.
βœ… Passed checks (4 passed)
Check name Status Explanation
Title check βœ… Passed The title clearly describes the main fix: ensuring the topmost modal maintains non-inert state, which is the core issue addressed by the changeset.
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/remove-inert-from-topmost-modal

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Size Change: +75 B (+0.01%)

Total Size: 656 kB

πŸ“¦ View Changed
Filename Size Change
dist/cjs/emojis.js 2.54 kB +1 B (+0.04%)
dist/cjs/index.js 255 kB +10 B (0%)
dist/cjs/ReactPlayerWrapper.js 545 B -1 B (-0.18%)
dist/cjs/useNotificationApi.js 49.8 kB +30 B (+0.06%)
dist/es/emojis.mjs 2.47 kB -2 B (-0.08%)
dist/es/index.mjs 251 kB +9 B (0%)
dist/es/useNotificationApi.mjs 48.6 kB +28 B (+0.06%)
ℹ️ View Unchanged
Filename Size
dist/cjs/audioProcessing.js 1.74 kB
dist/cjs/mp3-encoder.js 814 B
dist/css/emoji-picker.css 178 B
dist/css/emoji-replacement.css 456 B
dist/css/index.css 39.7 kB
dist/es/audioProcessing.mjs 1.65 kB
dist/es/mp3-encoder.mjs 768 B
dist/es/ReactPlayerWrapper.mjs 485 B

compressed-size-action

@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
βœ… Project coverage is 83.81%. Comparing base (4c934ae) to head (98bd5df).

Files with missing lines Patch % Lines
src/components/Dialog/service/DialogManager.ts 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3206      +/-   ##
==========================================
- Coverage   83.85%   83.81%   -0.05%     
==========================================
  Files         439      439              
  Lines       13203    13212       +9     
  Branches     4280     4286       +6     
==========================================
+ Hits        11071    11073       +2     
- Misses       2132     2139       +7     

β˜” View full report in Codecov by Sentry.
πŸ“’ Have feedback on the report? Share it here.

πŸš€ New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • πŸ“¦ JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@MartinCupela MartinCupela merged commit 7ad98fa into master Jun 4, 2026
11 checks passed
@MartinCupela MartinCupela deleted the fix/remove-inert-from-topmost-modal branch June 4, 2026 14:10
github-actions Bot pushed a commit that referenced this pull request Jun 5, 2026
## [14.4.0](v14.3.0...v14.4.0) (2026-06-05)

### Bug Fixes

* **compat:** restore React 17/18 compatibility in certain components ([#3197](#3197)) ([b513b69](b513b69))
* general performance and bug fixes ([#3201](#3201)) ([57c5795](57c5795))
* **interop:** unwrap CJS default exports (react-player, @emoji-mart/react) ([#3199](#3199)) ([4cddb02](4cddb02))
* maintain topmost modal non-inert ([#3206](#3206)) ([7ad98fa](7ad98fa))

### Features

* allow to stack modals on top of each other ([#3203](#3203)) ([4c934ae](4c934ae))
* display notifications above modals ([#3200](#3200)) ([0433090](0433090))
* **Reactions:** send emoji_code with reactions for push notification rendering ([#3209](#3209)) ([2faa620](2faa620))

### Performance Improvements

* **Message:** hoist regex compilation in message text rendering ([#3202](#3202)) ([8c018a4](8c018a4))
* **VideoPlayer:** lazy-load react-player to keep it out of the main bundle ([#3204](#3204)) ([18dc966](18dc966))
@stream-ci-bot

Copy link
Copy Markdown

πŸŽ‰ This PR is included in version 14.4.0 πŸŽ‰

The release is available on:

Your semantic-release bot πŸ“¦πŸš€

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants